package com.novel.system.controller;

import cn.hutool.core.util.ObjectUtil;
import com.novel.common.constants.Constants;
import com.novel.common.utils.StringUtils;
import com.novel.framework.annotation.Log;
import com.novel.framework.base.BaseController;
import com.novel.framework.enums.BusinessType;
import com.novel.framework.redis.ICacheService;
import com.novel.framework.result.Result;
import com.novel.framework.shiro.TokenService;
import com.novel.framework.web.page.TableDataInfo;
import com.novel.system.domain.LoginUser;
import com.novel.system.domain.SysUserOnline;
import com.novel.system.service.SysUserOnlineService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
 * 在线用户监控
 *
 * @author novel
 * @date 2019/12/20
 */
@RestController
@RequestMapping("/monitor/online")
public class SysUserOnlineController extends BaseController {
    private final ICacheService iCacheService;
    private final SysUserOnlineService sysUserOnlineService;
    private final TokenService tokenService;

    public SysUserOnlineController(ICacheService iCacheService, SysUserOnlineService sysUserOnlineService, TokenService tokenService) {
        this.iCacheService = iCacheService;
        this.sysUserOnlineService = sysUserOnlineService;
        this.tokenService = tokenService;
    }

    /**
     * 在线用户列表
     *
     * @param ipaddr   查询条件，ip地址
     * @param userName 查询条件，用户名
     * @return 在线用户列表
     */
    @RequiresPermissions("monitor:online:list")
    @GetMapping("/list")
    public TableDataInfo list(String ipaddr, String userName) {
        Set<String> keys = iCacheService.keys(Constants.ACCOUNT + "*");
        List<SysUserOnline> userOnlineList = new ArrayList<>();
        if (ObjectUtil.isNotNull(keys)) {
            List<LoginUser> loginUserList = iCacheService.multiGet(keys);
            for (LoginUser loginUser : loginUserList) {
                if (StringUtils.isNotNull(loginUser)) {
                    if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) {
                        if (StringUtils.equals(ipaddr, loginUser.getIpaddr())
                                && StringUtils.equals(userName, loginUser.getUser().getUserName())) {
                            SysUserOnline sysUserOnline = sysUserOnlineService.selectOnlineByInfo(ipaddr, userName, loginUser);
                            userOnlineList.add(sysUserOnline);
                        }
                    } else if (StringUtils.isNotEmpty(ipaddr)) {
                        if (StringUtils.equals(ipaddr, loginUser.getIpaddr())) {
                            SysUserOnline sysUserOnline = sysUserOnlineService.selectOnlineByIpaddr(ipaddr, loginUser);
                            userOnlineList.add(sysUserOnline);
                        }

                    } else if (StringUtils.isNotEmpty(userName)) {
                        if (StringUtils.equals(userName, loginUser.getUser().getUserName())) {
                            SysUserOnline sysUserOnline = sysUserOnlineService.selectOnlineByUserName(userName, loginUser);
                            userOnlineList.add(sysUserOnline);
                        }
                    } else {
                        SysUserOnline sysUserOnline = sysUserOnlineService.loginUserToUserOnline(loginUser);
                        userOnlineList.add(sysUserOnline);
                    }
                }
            }
        }
        userOnlineList.removeAll(Collections.singleton(null));
        Collections.sort(userOnlineList);
        return getDataTable(userOnlineList);
    }

    /**
     * 强退用户
     *
     * @param sessionId 用户会话id
     * @return 强退结果
     */
    @RequiresPermissions("monitor:online:forceLogout")
    @Log(title = "在线用户", businessType = BusinessType.FORCE)
    @DeleteMapping("/{sessionId}")
    public Result forceLogout(@PathVariable("sessionId") String sessionId) {
        tokenService.delLoginUsersBySessionId(sessionId);
        return success();
    }
}
